Skip to content

Migrate tests from MSTest to xUnit and clean up test infrastructure#193

Open
Copilot wants to merge 32 commits intomainfrom
copilot/resolve-mstest-warnings
Open

Migrate tests from MSTest to xUnit and clean up test infrastructure#193
Copilot wants to merge 32 commits intomainfrom
copilot/resolve-mstest-warnings

Conversation

Copy link
Contributor

Copilot AI commented Feb 4, 2026

Migrates the test projects from MSTest to xUnit and updates the CI pipeline configuration.

Test Framework Migration (MSTest → xUnit)

  • Replaced MSTest with xUnit (v2.9.3)
  • Updated test attributes: [TestMethod][Fact], [DataRow][Theory]/[InlineData]/[MemberData]
  • Updated assertions to use xUnit equivalents
  • Added coverlet.collector for code coverage

Pipeline Updates

  • Updated dotnetTestArgs to use --settings coverlet.runsettings --collect:"XPlat Code Coverage"
  • Added coverlet.runsettings file to configure coverage output format (cobertura,opencover) for ADO pipeline compatibility
  • Added PublishCodeCoverageResults@2 task via postTest parameter to publish code coverage results to Azure DevOps

Code Cleanup

  • Fixed indentation issues in test files
  • Removed obsolete MSTest-specific configurations
Original prompt

When running the tests in this repository I see a number of MSTest warnings in the logs. I also notice that the ado pipeline at the end of the run notes ##[warning]No test result files were found. Can you resolve these test warnings and the issue that the test results (and presumably code coverage) is not being properly consumed by the pipeline? If needed to perform a restore you may modify the nuget.config to use the public feed instead of the private feed but do not commit changes to nuget.config.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 2 commits February 4, 2026 21:58
Co-authored-by: gfs <98900+gfs@users.noreply.github.com>
Co-authored-by: gfs <98900+gfs@users.noreply.github.com>
@gfs
Copy link
Contributor

gfs commented Feb 4, 2026

@copilot try again please

…ectedException, duplicate DataRows, add parallelization, use Assert.HasCount/IsEmpty/IsGreaterThan, add CancellationToken support. Update pipeline to use standard trx logger with results directory.

Co-authored-by: gfs <98900+gfs@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 4, 2026

@copilot try again please

Fixed all MSTest warnings in commit cca4e14. The changes include:

  • Replaced [DataTestMethod] with [TestMethod] (MSTEST0044)
  • Replaced Assert.ThrowsException with Assert.ThrowsExactly (MSTEST0039)
  • Replaced [ExpectedException] with Assert.ThrowsExactly (MSTEST0006)
  • Replaced Assert.AreEqual(n, collection.Count) with Assert.HasCount(n, collection) (MSTEST0037)
  • Removed duplicate DataRow attributes (MSTEST0042)
  • Added [assembly: Parallelize] attribute (MSTEST0001)
  • Added TestContext property and CancellationToken support to async tests (MSTEST0049)
  • Updated pipeline to use --logger trx --results-directory for proper test result file output

Build now succeeds with 0 warnings and 0 errors.

@gfs
Copy link
Contributor

gfs commented Feb 4, 2026

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request addresses MSTest warnings in the test output and fixes the Azure DevOps pipeline test result handling. The changes modernize the test code to use newer MSTest 3.x assertion methods and configuration patterns, and ensure test results are properly published to the pipeline.

Changes:

  • Fixed MSTest warnings (MSTEST0001, 0006, 0037, 0039, 0042, 0044, 0049) by replacing deprecated patterns with modern MSTest 3.x equivalents
  • Updated Azure Pipelines YAML files to properly specify test result output location and format
  • Added test parallelization configuration and cancellation token support for async tests

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated no comments.

Show a summary per file
File Description
RecursiveExtractor.Tests/AssemblyInfo.cs Added assembly-level Parallelize attribute for MSTEST0001 compliance
RecursiveExtractor.Tests/ExtractorTests/BaseExtractorTestClass.cs Added TestContext property for MSTEST0049 compliance
RecursiveExtractor.Tests/ExtractorTests/CustomExtractorTests.cs Added TestContext property; replaced Assert.AreEqual with Assert.HasCount/IsEmpty/IsGreaterThan for MSTEST0037
RecursiveExtractor.Tests/ExtractorTests/DisposeBehaviorTests.cs Replaced DataTestMethod with TestMethod; removed duplicate DataRow attributes; replaced Assert.ThrowsException with Assert.ThrowsExactly for MSTEST0044, 0042, 0039
RecursiveExtractor.Tests/ExtractorTests/EncryptedArchiveTests.cs Replaced DataTestMethod with TestMethod for MSTEST0044
RecursiveExtractor.Tests/ExtractorTests/FilterTests.cs Replaced DataTestMethod with TestMethod for MSTEST0044
RecursiveExtractor.Tests/ExtractorTests/MiniMagicTests.cs Replaced DataTestMethod with TestMethod for MSTEST0044
RecursiveExtractor.Tests/ExtractorTests/MiscTests.cs Added TestContext property; replaced DataTestMethod with TestMethod; replaced Assert.AreEqual with Assert.HasCount; added CancellationToken to ToListAsync calls for MSTEST0049, 0044, 0037
RecursiveExtractor.Tests/ExtractorTests/TestQuinesAndSlip.cs Replaced ExpectedException with Assert.ThrowsExactly/ThrowsExactlyAsync; added CancellationToken to ToListAsync calls for MSTEST0006, 0049
RecursiveExtractor.Tests/ExtractorTests/TimeOutTests.cs Replaced DataTestMethod with TestMethod; removed duplicate DataRow attributes; replaced Assert.ThrowsException with Assert.ThrowsExactly/ThrowsExactlyAsync for MSTEST0044, 0042, 0039
RecursiveExtractor.Tests/SanitizePathTests.cs Replaced DataTestMethod with TestMethod for MSTEST0044
Pipelines/recursive-extractor-pr.yml Updated dotnetTestArgs to properly specify TRX output location for test result publishing
Pipelines/recursive-extractor-release.yml Updated dotnetTestArgs to properly specify TRX output location for test result publishing

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@gfs
Copy link
Contributor

gfs commented Feb 5, 2026

@copilot this change breaks the PR gates - now see Option '--results-directory' expects a single argument but 2 were provided. intead of executing the tests

…sing error

Co-authored-by: gfs <98900+gfs@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 5, 2026

@copilot this change breaks the PR gates - now see Option '--results-directory' expects a single argument but 2 were provided. intead of executing the tests

Fixed in bdfa42c. Reverted the pipeline dotnetTestArgs back to the original format '-- --coverage --report-trx'. The --results-directory argument was causing the parsing error because of the path variable expansion. The MSTest Testing Platform's --report-trx flag will generate TRX files automatically in the output directory.

Copilot AI changed the title [WIP] Fix MSTest warnings and update pipeline test result handling Fix MSTest warnings and update test code to modern patterns Feb 5, 2026
@gfs
Copy link
Contributor

gfs commented Feb 5, 2026

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@gfs
Copy link
Contributor

gfs commented Feb 5, 2026

@copilot I still see no test result files found in azure dev ops along with. couple test failures, but without the test results being parsed its very hard to debug which tests are failing. can you fix the test result files and code coverage properly?

…ectory

Co-authored-by: gfs <98900+gfs@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 5, 2026

@copilot I still see no test result files found in azure dev ops along with. couple test failures, but without the test results being parsed its very hard to debug which tests are fa...

Fixed in 1e3c7b2. Changed the pipeline dotnetTestArgs to use --logger trx --results-directory TestResults -- --coverage. This uses the standard VSTest TRX logger with a relative path for the results directory (avoiding the path parsing issue we had before with $(Build.SourcesDirectory)/TestResults). The TRX files will now be generated in a TestResults folder that the pipeline template should be able to locate with its standard glob patterns.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 29 out of 29 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (3)

RecursiveExtractor.Tests/ExtractorTests/DisposeBehaviorTests.cs:150

  • Poor error handling: empty catch block.
        catch (DirectoryNotFoundException) { }

RecursiveExtractor.Tests/ExtractorTests/DisposeBehaviorTests.cs:174

  • Poor error handling: empty catch block.
        catch (DirectoryNotFoundException) { }

RecursiveExtractor.Tests/ExtractorTests/DisposeBehaviorTests.cs:182

  • Poor error handling: empty catch block.
        catch (DirectoryNotFoundException) { }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Test classes now use IClassFixture<BaseExtractorTestClass> for improved setup/teardown and isolation. BaseExtractorTestClass implements IDisposable for proper cleanup. Added documentation and updated using statements. Minor formatting and code organization improvements.
@gfs
Copy link
Contributor

gfs commented Feb 6, 2026

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 29 out of 29 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (3)

RecursiveExtractor.Tests/ExtractorTests/DisposeBehaviorTests.cs:150

  • Poor error handling: empty catch block.
        catch (DirectoryNotFoundException) { }

RecursiveExtractor.Tests/ExtractorTests/DisposeBehaviorTests.cs:174

  • Poor error handling: empty catch block.
        catch (DirectoryNotFoundException) { }

RecursiveExtractor.Tests/ExtractorTests/DisposeBehaviorTests.cs:182

  • Poor error handling: empty catch block.
        catch (DirectoryNotFoundException) { }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

gfs and others added 3 commits February 5, 2026 22:47
Replaced individual class fixtures with a shared ExtractorTestCollection using Xunit's [CollectionDefinition] and ICollectionFixture<BaseExtractorTestClass>. This ensures all extractor test classes share a single fixture instance, preventing race conditions and premature deletion of shared resources during parallel test execution.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@gfs
Copy link
Contributor

gfs commented Feb 6, 2026

/azp run

@gfs gfs requested a review from Copilot February 6, 2026 06:48
@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

gfs added 2 commits February 5, 2026 22:51
Replaced IEnumerable<object[]> with TheoryData<string> for ZipSlipNames and QuineBombNames, improving type safety and clarity in parameterized tests. Removed unused using directives for cleaner code.
@gfs
Copy link
Contributor

gfs commented Feb 6, 2026

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 30 out of 30 changed files in this pull request and generated 6 comments.

Comments suppressed due to low confidence (3)

RecursiveExtractor.Tests/ExtractorTests/DisposeBehaviorTests.cs:151

  • Poor error handling: empty catch block.
        catch (DirectoryNotFoundException) { }

RecursiveExtractor.Tests/ExtractorTests/DisposeBehaviorTests.cs:175

  • Poor error handling: empty catch block.
        catch (DirectoryNotFoundException) { }

RecursiveExtractor.Tests/ExtractorTests/DisposeBehaviorTests.cs:183

  • Poor error handling: empty catch block.
        catch (DirectoryNotFoundException) { }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


[TestClass]
public class FilterTests : BaseExtractorTestClass
[Collection(ExtractorTestCollection.Name)]
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test class doesn't use TestPathHelpers.GetFreshTestDirectory() and doesn't need to be in the ExtractorTestCollection. The Collection attribute can be removed to allow this test class to run in parallel with other test classes. The Collection is primarily needed for test classes that share the test directory cleanup fixture (currently only ExpectedNumFilesTests and DisposeBehaviorTests).

Suggested change
[Collection(ExtractorTestCollection.Name)]

Copilot uses AI. Check for mistakes.

[TestClass]
public class MiniMagicTests : BaseExtractorTestClass
[Collection(ExtractorTestCollection.Name)]
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test class doesn't use TestPathHelpers.GetFreshTestDirectory() and doesn't need to be in the ExtractorTestCollection. The Collection attribute can be removed to allow this test class to run in parallel with other test classes. The Collection is primarily needed for test classes that share the test directory cleanup fixture (currently only ExpectedNumFilesTests and DisposeBehaviorTests).

Suggested change
[Collection(ExtractorTestCollection.Name)]

Copilot uses AI. Check for mistakes.

[TestClass]
public class TimeOutTests : BaseExtractorTestClass
[Collection(ExtractorTestCollection.Name)]
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test class doesn't use TestPathHelpers.GetFreshTestDirectory() and doesn't need to be in the ExtractorTestCollection. The Collection attribute can be removed to allow this test class to run in parallel with other test classes. The Collection is primarily needed for test classes that share the test directory cleanup fixture (currently only ExpectedNumFilesTests and DisposeBehaviorTests).

Suggested change
[Collection(ExtractorTestCollection.Name)]

Copilot uses AI. Check for mistakes.

[TestClass]
public class TestQuinesAndSlip : BaseExtractorTestClass
[Collection(ExtractorTestCollection.Name)]
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test class doesn't use TestPathHelpers.GetFreshTestDirectory() and doesn't need to be in the ExtractorTestCollection. The Collection attribute can be removed to allow this test class to run in parallel with other test classes. The Collection is primarily needed for test classes that share the test directory cleanup fixture (currently only ExpectedNumFilesTests and DisposeBehaviorTests).

Suggested change
[Collection(ExtractorTestCollection.Name)]

Copilot uses AI. Check for mistakes.

[TestClass]
public class EncryptedArchiveTests : BaseExtractorTestClass
[Collection(ExtractorTestCollection.Name)]
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test class doesn't use TestPathHelpers.GetFreshTestDirectory() and doesn't need to be in the ExtractorTestCollection. The Collection attribute can be removed to allow this test class to run in parallel with other test classes. The Collection is primarily needed for test classes that share the test directory cleanup fixture (currently only ExpectedNumFilesTests and DisposeBehaviorTests).

Suggested change
[Collection(ExtractorTestCollection.Name)]

Copilot uses AI. Check for mistakes.
}
if (Directory.Exists(copyDirectory)) {
Directory.Delete(copyDirectory, true);
catch (DirectoryNotFoundException) { }
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Poor error handling: empty catch block.

This issue also appears in the following locations of the same file:

  • line 151
  • line 175
  • line 183

Copilot uses AI. Check for mistakes.
Suppressed CS1685 warning in the test project due to a RuntimeHelpers polyfill conflict on net48. Removed DiscUtils Btrfs, HfsPlus, SquashFs, and Xfs package references from the test project -  they are already imported when needed in the main project which is then imported into the test project to test it
@gfs
Copy link
Contributor

gfs commented Feb 6, 2026

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Removed the [Collection(ExtractorTestCollection.Name)] attribute from EncryptedArchiveTests, FilterTests, MiniMagicTests, TestQuinesAndSlip, and TimeOutTests. These test classes are no longer grouped in a shared test collection - the collection was used to protect against premature deletion of the temp directory but these tsts don't extract files to disc.
@gfs
Copy link
Contributor

gfs commented Feb 6, 2026

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

gfs added 2 commits February 5, 2026 23:15
Index and Range polyfills were removed since they are now provided
by Microsoft.Bcl.Memory as a transitive dependency. The file retains
only the RuntimeHelpers.GetSubArray polyfill for array range syntax
support on netstandard2.0.
Added the null-forgiving operator (`!`) to the `name` variable in the `while` loop condition to suppress potential null reference warnings.  `name` is expected to be non-null at this point in the code becauses of the previous IsNullorEmpty check - however that isn't tagged on netstandard2.0.
@gfs
Copy link
Contributor

gfs commented Feb 6, 2026

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants